/***************************************************************************
 *            draw_test.c
 *
 *  Tue May 29 11:14:31 2007
 *  Copyright  2007  kf701
 *  Email <kf701.ye AT gmail.com>
 ****************************************************************************/

#include <math.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <asm/page.h>
#include <linux/fb.h>

#include "kf701.h"

typedef struct fbdev{
	int fb;
	unsigned long fb_mem_offset;
	unsigned long fb_mem;
	struct fb_fix_screeninfo fb_fix;
	struct fb_var_screeninfo fb_var;
	char dev[20];
} FBDEV, *PFBDEV;

PFBDEV pFbdev;

int fb_open()
{
	pFbdev->fb = open(pFbdev->dev, O_RDWR);
	if(pFbdev->fb < 0)
	{
		printf("Error opening %s: %m. Check kernel config\n", pFbdev->dev);
		return -1;
	}
	if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))
	{
		printf("ioctl FBIOGET_VSCREENINFO\n");
		return -1;
	}
	if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))
	{
		printf("ioctl FBIOGET_FSCREENINFO\n");
		return -1;
	}

	pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
	pFbdev->fb_mem = (unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len + 
			pFbdev->fb_mem_offset,
			PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0);
	if (-1L == (long) pFbdev->fb_mem) 
	{
		printf("mmap error! mem:%ld offset:%ld\n", pFbdev->fb_mem, 
				pFbdev->fb_mem_offset);
		return -1;
	}

	printf("depth(bits per pixel) =  %d\n",pFbdev->fb_var.bits_per_pixel);
	printf("smemlen = %d\n",pFbdev->fb_fix.smem_len);
	printf("fix_line(in byte) = %d\n",pFbdev->fb_fix.line_length);

	return 0;
}

void fb_close()
{
	close(pFbdev->fb);
	pFbdev->fb=-1;
}

void fb_memcpy(void *addr, void *color, size_t len)
{
	memcpy(addr, color, len);
}

void dot (point_t p, color_t color)
{
	uint32_t offset;
	uint8_t color_buf[4];
	color_buf[0] = color.b;
	color_buf[1] = color.g;
	color_buf[2] = color.r;
	color_buf[3] = color.a;
	offset = p.y*pFbdev->fb_fix.line_length+4*p.x;
	fb_memcpy((void*)(pFbdev->fb_mem + pFbdev->fb_mem_offset + offset), color_buf, 4);
}

int main(void)
{
	pFbdev = (PFBDEV)malloc(sizeof(FBDEV));
	memset(pFbdev, 0, sizeof(FBDEV));
	strcpy(pFbdev->dev, "/dev/fb0");
	if(fb_open()==-1)
	{
		printf("open frame buffer error\n");
		return 0;
	}

	point_t p1, p2, p3;
	p1.x = 200;
	p1.y = 200;
	p2.x = 300;
	p2.y = 400;
	p3.x = 500;
	p3.y = 250;

	color_t color;
	color.r = 0x0;
	color.g = 0xff;
	color.b = 0x0;
	color.a = 0x0;

	draw_triangle(p1, p2, p3, color, dot);
	
	point_t center = { 400, 500, 0 };
	int radius = 100;
	draw_circle( center, radius, color, dot);

	center.x = 700;
	center.y = 250;
	int a = -100;
	draw_parabola_x( center, a, color, dot);
	draw_parabola_x( center, -a, color, dot);
	draw_parabola_y( center, a, color, dot);
	draw_parabola_y( center, -a, color, dot);

	fb_close();
	return 0;
}
